//
//  CurvesView.m
//  ToneMapper
//
//  Created by Andrey on 03/04/2009.
//  Copyright 2009 Karma Software. All rights reserved.
//

#import "CurvesView.h"
#import "KCurve.h"

#define CURVES_WINDOW_SIZE 400
#define GRID_LINE_COUNT 10

@implementation CurvesView

@synthesize curve;

- (id)initWithFrame:(NSRect)frame 
{
    self = [super initWithFrame:frame];

    if (self) 
	{
        curve = [[[KCurve alloc] init] retain];
		
		[curve addControlPoint:NSMakePoint(0.0, 0.0)];
		[curve addControlPoint:
		 NSMakePoint(CURVES_WINDOW_SIZE / CURVES_WINDOW_SIZE, 
					 CURVES_WINDOW_SIZE / CURVES_WINDOW_SIZE)];
		
		selectedCurveControlPoint = -1;
	}
	
    return self;
}

- (BOOL) acceptsFirstResponder
{
	return YES;
}

- (NSInteger)findNearbyControlPoint:(NSPoint) point
{
	for (int i = 0; i < [curve.controlPoints count]; i++)
	{
		NSPoint controlPoint = [[curve.controlPoints objectAtIndex:i] pointValue];
		CGFloat deltaX = point.x - controlPoint.x;
		CGFloat deltaY = point.y - controlPoint.y;
		if (deltaX * deltaX + deltaY * deltaY < 5.0 / CURVES_WINDOW_SIZE)
			return i;
	}
	
	return -1;
}

- (void)mouseDown:(NSEvent *)theEvent
{
	NSPoint mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil];
	mouseLocation.x /= CURVES_WINDOW_SIZE;
	mouseLocation.y /= CURVES_WINDOW_SIZE;
	
	NSInteger nearbyControlPoint = [self findNearbyControlPoint: mouseLocation];
	if (nearbyControlPoint == -1)
	{
		[curve addControlPoint:mouseLocation];
		selectedCurveControlPoint = 
		[curve.controlPoints indexOfObject:[NSValue valueWithPoint:mouseLocation]];
	}
	else
		selectedCurveControlPoint = nearbyControlPoint;
	
	[self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)rect 
{
    // Draw grid
	NSBezierPath* grid = [NSBezierPath bezierPath];
	CGFloat gridStep = CURVES_WINDOW_SIZE / GRID_LINE_COUNT;
	[[NSColor grayColor] set];
	for (int i = 0; i <= rect.size.width; i += gridStep)
	{
		[grid moveToPoint:NSMakePoint(i, 0)];
		[grid lineToPoint:NSMakePoint(i, rect.size.height)];
		[grid moveToPoint:NSMakePoint(0, i)];
		[grid lineToPoint:NSMakePoint(rect.size.width, i)];
	}
	[grid stroke];
	
	// Draw curve
	[[NSColor lightGrayColor] set];
	NSBezierPath* curvePath = [NSBezierPath bezierPath];
	[curvePath moveToPoint:NSMakePoint(0, 0)];
	for (int x = 0; x < rect.size.width; x++)
	{
		CGFloat t = (CGFloat)x / rect.size.width;
		[curvePath lineToPoint:NSMakePoint(x, [curve valueAt:t] * CURVES_WINDOW_SIZE)];
	}
	[curvePath stroke];
	
	// Draw control points
	NSBezierPath* controlPoints = [NSBezierPath bezierPath];
	for (int i = 0; i < [curve.controlPoints count]; i++)
	{			
		CGFloat x = [[curve.controlPoints objectAtIndex:i] pointValue].x * CURVES_WINDOW_SIZE;
		CGFloat y = [[curve.controlPoints objectAtIndex:i] pointValue].y * CURVES_WINDOW_SIZE;
		
		NSRect circleRect = NSMakeRect(x - 3, y - 3, 6, 6);
		
		[controlPoints appendBezierPathWithOvalInRect:circleRect];
	}
	[controlPoints fill];
	
	// Draw selected control point
	if (selectedCurveControlPoint != -1)
	{
		[[NSColor whiteColor] set];
		[controlPoints removeAllPoints];
		CGFloat x = 
		[[curve.controlPoints objectAtIndex:selectedCurveControlPoint] pointValue].x * CURVES_WINDOW_SIZE;
		CGFloat y = 
		[[curve.controlPoints objectAtIndex:selectedCurveControlPoint] pointValue].y * CURVES_WINDOW_SIZE;
		NSRect circleRect = NSMakeRect(x - 3, y - 3, 6, 6);
		
		[controlPoints appendBezierPathWithOvalInRect:circleRect];
		[controlPoints fill];
	}
}

- (void)dealloc
{
	[curve release];
	[super dealloc];
}
@end
